lexer grammar Language;
@members {
    class SaveStruct {
      SaveStruct(CharStream input){
        this.input = input;
        this.marker = input.mark();
      }
      public CharStream input;
      public int marker;
      public File basePath;
     }
     
     File basePath = new File(".");
     public void setBasePath(String path){
     	basePath = new File(path);
     }
     

     Stack<SaveStruct> includes = new Stack<SaveStruct>();

    // We should override this method for handling EOF of included file
     public Token nextToken(){
       Token token = super.nextToken();

       if(token==Token.EOF_TOKEN && !includes.empty()){
        // We've got EOF and have non empty stack.
         SaveStruct ss = includes.pop();
         basePath = ss.basePath;
         setCharStream(ss.input);
         input.rewind(ss.marker);
         token = super.nextToken();
       }

      // Skip first token after switching on another input.
      // You need to use this rather than super as there may be nested include files
       if(((CommonToken)token).getStartIndex() < 0)
         token = this.nextToken();

       return token;
     }
 }
@header {
package ac.jp.u_tokyo.SyncLib.language;
import java.io.File;
}

CONST : 'const' ;
GRAPH : 'graph' ;
SWITCH : 'switch' ;
DICTMAP : 'map' ;
EMAP : 'emap' ;
KMAP : 'kmap' ;
NATIVE : 'native' ;
FACTORY : 'factory' ;
TRUE : 'true' ;
FALSE : 'false' ;
OPTION : 'option' ;
CLASS : 'classref' ;
VAR : 'var' ;
VARS : 'vars' ;
PARAMETERS : 'parameters' ;
FACTORIES : 'factories' ;
DICTS : 'dicts' ;
SYNC : 'sync' ;
NULL : 'null' ;
T34 : '=' ;
T35 : '<' ;
T36 : ',' ;
T37 : '>' ;
T38 : '{' ;
T39 : ';' ;
T40 : '}' ;
T41 : '[' ;
T42 : ']' ;
T43 : '(' ;
T44 : ')' ;

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 82
fragment DIGIT 
	:	'0'..'9';
	
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 85
fragment ULETTER
	:	'A'..'Z';
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 87
fragment LLETTER
	:	'a'..'z';
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 89
fragment LETTER
	:	ULETTER | LLETTER | '_';	

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 92
NUMBER : DIGIT+;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 93
NAME 	:	LETTER (DIGIT | LETTER)*;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 94
STRING : ('\"' | '\'') (~('\"' | '\''))* ('\"' | '\'');


// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 97
COMMENT			
		:	'/*'  ( options {greedy=false;}:.)* '*/' 			  {skip();}
		|	'/' '\\' '\n' '*'  ( options {greedy=false;}:.)* '*/' {skip();}
		;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 101
LINE_COMMENT :	'//'(~('\n' | '\r')*)('\n' | '\r') {skip();};

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 103
WS
    : (' '| '\t' | '\n' | '\r')+ {skip();};
    
 // $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language\Language.g" 106
INCLUDE
     : 'include' (WS)? f=STRING {
       String name = f.getText();
       name = name.substring(1,name.length()-1);
       try {
        // save current lexer's state
         SaveStruct ss = new SaveStruct(input);
         ss.basePath = basePath;
         includes.push(ss);
         
         name = basePath.getAbsolutePath() + File.separator + name;
         basePath = new File(name).getAbsoluteFile().getParentFile();

        // switch on new input stream
         setCharStream(new ANTLRFileStream(name));
         reset();

       } catch(Exception fnf) { throw new Error("Cannot open file " + name); }
     }
     ;
    
  
    
    
    
